package com.iflytek.aiui.voiceclone.util;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.hc.client5.http.ClientProtocolException;
import org.apache.hc.client5.http.classic.methods.HttpDelete;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.classic.methods.HttpPost;
import org.apache.hc.client5.http.classic.methods.HttpUriRequest;
import org.apache.hc.client5.http.config.RequestConfig;
import org.apache.hc.client5.http.entity.UrlEncodedFormEntity;
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
import org.apache.hc.client5.http.impl.classic.HttpClients;
import org.apache.hc.core5.http.HttpEntity;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.NameValuePair;
import org.apache.hc.core5.http.ParseException;
import org.apache.hc.core5.http.io.HttpClientResponseHandler;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.apache.hc.core5.http.io.entity.StringEntity;

import com.alibaba.fastjson.JSON;

/**
 * HTTP 请求工具类
 *
 */
public class HttpUtil {

	private static HttpClientResponseHandler<String> DEFAULT_REPONSE_HANDLER = response -> {
        final int status = response.getCode();
        final HttpEntity entity = response.getEntity();
        if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
            try {
                return entity != null ? EntityUtils.toString(entity) : null;
            } catch (final ParseException ex) {
                throw new ClientProtocolException(ex);
            }
        } else {
        	String errBodyMsg = entity != null ? EntityUtils.toString(entity) : "";
            throw new ClientProtocolException("Unexpected response status: " + status + ", errBodyMsg: " + errBodyMsg);
        }
    };

    public static HttpClientResponseHandler<byte[]> BYTES_REPONSE_HANDLER = response -> {
        final int status = response.getCode();
        final HttpEntity entity = response.getEntity();
        if (status >= HttpStatus.SC_SUCCESS && status < HttpStatus.SC_REDIRECTION) {
            return entity != null ? EntityUtils.toByteArray(entity) : null;
        } else {
            String errBodyMsg = entity != null ? EntityUtils.toString(entity) : "";
            throw new ClientProtocolException("Unexpected response status: " + status + ", errBodyMsg: " + errBodyMsg);
        }
    };

    private static final RequestConfig DEFAULT_TIME_OUT = RequestConfig.custom()
            .setConnectTimeout(10000, TimeUnit.MILLISECONDS)
            .setConnectionRequestTimeout(30000, TimeUnit.MILLISECONDS)
            .setResponseTimeout(1800, TimeUnit.SECONDS).build();

	public static String post(String url, Object jsonBody) throws IOException {
		HttpPost httpPost = new HttpPost(url);
		httpPost.setHeader("Content-Type", "application/json");
		if (jsonBody != null) {
			httpPost.setEntity(new StringEntity(JSON.toJSONString(jsonBody), Charset.forName("utf-8")));
		}
		httpPost.setConfig(DEFAULT_TIME_OUT);

		return sendRequest(httpPost);
	}

	public static byte[] postWithByteRes(String url, Object jsonBody) throws IOException {
	    HttpPost httpPost = new HttpPost(url);
	    httpPost.setHeader("Content-Type", "application/json");
	    if (jsonBody != null) {
	        httpPost.setEntity(new StringEntity(JSON.toJSONString(jsonBody), Charset.forName("utf-8")));
	    }
	    httpPost.setConfig(DEFAULT_TIME_OUT);

	    return sendRequest(httpPost, BYTES_REPONSE_HANDLER);
	}

	public static String post(String url, String jsonBody) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json");
        httpPost.setEntity(new StringEntity(jsonBody, Charset.forName("utf-8")));
        httpPost.setConfig(DEFAULT_TIME_OUT);

        return sendRequest(httpPost);
    }

	public static String get(String url) throws IOException {
	    HttpGet httpGet = new HttpGet(url);
	    httpGet.setConfig(DEFAULT_TIME_OUT);
	    return sendRequest(httpGet);
	}

	public static String delete(String url) throws IOException {
	    HttpDelete httpDelete = new HttpDelete(url);
	    httpDelete.setConfig(DEFAULT_TIME_OUT);
	    return sendRequest(httpDelete);
	}

	public static String delete(String url, Object jsonBody) throws IOException {
	    HttpDelete httpDelete = new HttpDelete(url);
	    httpDelete.setHeader("Content-Type", "application/json");
	    if (jsonBody != null) {
	        httpDelete.setEntity(new StringEntity(JSON.toJSONString(jsonBody), Charset.forName("utf-8")));
        }
	    httpDelete.setConfig(DEFAULT_TIME_OUT);

        return sendRequest(httpDelete);
    }

    public static String post(String url) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(DEFAULT_TIME_OUT);
        return sendRequest(httpPost);
    }

	public static String get(String url, String cookie) throws IOException {
        HttpGet httpGet = new HttpGet(url);
        httpGet.addHeader("Cookie", cookie);
        httpGet.setConfig(DEFAULT_TIME_OUT);
        return sendRequest(httpGet);
    }

	public static String postFormUrlencoded(String url, List<NameValuePair> params) throws IOException {
        HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(DEFAULT_TIME_OUT);
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        httpPost.setEntity(new UrlEncodedFormEntity(params, Charset.forName("UTF-8")));
        return sendRequest(httpPost);
    }

	public static String postWithEntity(String url, HttpEntity entity) throws IOException {
	    HttpPost httpPost = new HttpPost(url);
        httpPost.setConfig(DEFAULT_TIME_OUT);
        httpPost.setEntity(entity);
        return sendRequest(httpPost);
	}

	public static String sendRequest(HttpUriRequest request) throws IOException {
		try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
			return httpClient.execute(request, DEFAULT_REPONSE_HANDLER);
		}
	}

	public static <T> T sendRequest(HttpUriRequest request, HttpClientResponseHandler<T> h) throws IOException {
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            return httpClient.execute(request, h);
        }
    }
}
